package Printer;

import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.Build;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.Toast;

import androidx.annotation.RequiresApi;

import com.caysn.autoreplyprint.AutoReplyPrint;
import com.sun.jna.Pointer;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import utils.MyUtil;

public class UsbPrinter {
    private Context usbCtx;
    public String command = ""; //打印命令字符串
    public byte[] outbytes; //传输的命令集
    PrinterCMD pcmd = new PrinterCMD();

    public List<String> usb_list;
    public ArrayAdapter<String> arr_adapter;

    public UsbManager usbManager;
    public List<UsbDevice> usb_device;
    public UsbDevice device;
    /**
     * 满足的设备
     */
    public UsbDevice myUsbDevice;
    /**
     * usb接口
     */
    public UsbInterface usbInterface;
    /**
     * 块输出端点
     */
    public UsbEndpoint epBulkOut;
    public UsbEndpoint epBulkIn;
    /**
     * 中断端点
     */
    public UsbEndpoint epIntEndpointOut;
    public UsbEndpoint epIntEndpointIn;
    /**
     * 连接
     */
    public UsbDeviceConnection myDeviceConnection;

    public static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
    public PendingIntent permissionIntent;

    /**
     * 枚举设备
     */
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public void enumeraterDevices(Context ctx, Spinner s) {
        usbCtx = ctx;

        HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
        Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();

        usb_list = new ArrayList<String>();
        usb_device = new ArrayList<UsbDevice>();

        while(deviceIterator.hasNext()) {
            device = deviceIterator.next();
            if (device.getProductName().indexOf("Print") != -1
                    || device.getProductName().indexOf("print") != -1
            ) {
                usb_list.add(device.getDeviceName()
                                +" ("
                                +device.getManufacturerName()
//                        +",VID:"+device.getVendorId()
//                        +",PID:"+device.getProductId()
                                +")"
                );
                usb_device.add(device);
            }
        }

        //适配器
        arr_adapter= new ArrayAdapter<String>(ctx, android.R.layout.simple_spinner_item, usb_list);
        //设置样式
        arr_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        //加载适配器
        s.setAdapter(arr_adapter);
    }

    public final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
        @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (ACTION_USB_PERMISSION.equals(action)) {
                synchronized (this) {
                    device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                        if(device != null){
                            //call method to set up device communication 打开设备
//                            System.out.println("printerInfoStr-->BroadcastReceiver:"+device.getVendorId()+":"+device.getProductId());
                        }
                    } else {
//                        System.out.println("printerInfoStr-->permission denied for device " + device);
//                        Toast.makeText(context, "请再次连接打印机获取权限!", Toast.LENGTH_SHORT).show();
                    }
                }
            } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
//                System.out.println("printerInfoStr-->关闭");
                Toast.makeText(context, "USB打印机已断开连接!", Toast.LENGTH_SHORT).show();
            }
        }
    };

    /**
     * 获取设备的接口
     */
    private void getDeviceInterface() {
        if (myUsbDevice!=null) {
            usbInterface = myUsbDevice.getInterface(0);
//            System.out.println("printerInfoStr-->getDeviceInterface:" + myUsbDevice.getInterfaceCount());
//            System.out.println("printerInfoStr-->usbInterface.getId():" + usbInterface.getId());
        }
    }

    /**
     * 分配端点，IN | OUT，即输入输出；可以通过判断
     */
    private void assignEndpoint() {
        if(usbInterface!=null){
            for (int i = 0; i < usbInterface.getEndpointCount(); i++) {
                UsbEndpoint ep = usbInterface.getEndpoint(i);
                switch (ep.getType()){
                    case UsbConstants.USB_ENDPOINT_XFER_BULK://块
                        if(UsbConstants.USB_DIR_OUT==ep.getDirection()){//输出
                            epBulkOut = ep;
//                            System.out.println("printerInfoStr-->Find the BulkEndpointOut," + "index:" + i + "," + "使用端点号："+ epBulkOut.getEndpointNumber());
                        }else{
                            epBulkIn = ep;
//                            System.out .println("printerInfoStr-->Find the BulkEndpointIn:" + "index:" + i+ "," + "使用端点号："+ epBulkIn.getEndpointNumber());
                        }
                        break;
                    case UsbConstants.USB_ENDPOINT_XFER_CONTROL://控制
                        /**
                         * 控制端点
                         */
//                        System.out.println("printerInfoStr-->find the ControlEndPoint:" + "index:" + i+ "," + ep.getEndpointNumber());
                        break;
                    case UsbConstants.USB_ENDPOINT_XFER_INT://中断
                        if (ep.getDirection() == UsbConstants.USB_DIR_OUT) {//输出
                            epIntEndpointOut = ep;
//                            System.out.println("printerInfoStr-->find the InterruptEndpointOut:" + "index:" + i + ","  + epIntEndpointOut.getEndpointNumber());
                        }
                        if (ep.getDirection() == UsbConstants.USB_DIR_IN) {
                            epIntEndpointIn = ep;
//                            System.out.println("printerInfoStr-->find the InterruptEndpointIn:" + "index:" + i + ","+ epIntEndpointIn.getEndpointNumber());
                        }
                        break;
                    default:
                        throw new IllegalStateException("Unexpected value: " + ep.getType());
                }
            }
        }
    }


    /**
     * 连接设备
     */
    public String open() {
        getDeviceInterface();
        assignEndpoint();
        if(usbInterface!=null){//接口是否为null
            // 在open前判断是否有连接权限；对于连接权限可以静态分配，也可以动态分配权限
            UsbDeviceConnection conn = null;
            if(usbManager.hasPermission(myUsbDevice)){
                //有权限，那么打开
                conn = usbManager.openDevice(myUsbDevice);
                if(null==conn){
                    return "无法连接到打印机";
                }
                //打开设备
                if(conn.claimInterface(usbInterface,true)){
                    myDeviceConnection = conn;
                    // 到此你的android设备已经连上zigbee设备
                    return "success";
                } else {
                    conn.close();
                    return "无法打开连接通道";
                }
            } else {
//                usbManager.requestPermission(myUsbDevice, permissionIntent);
                return "没有权限";
            }

        } else {
            return "usbInterface is null";
        }
    }

    /*
    * usb设备断开连接
    * */
    public String close() {
        try {
            if(myDeviceConnection != null) {
                myDeviceConnection.close();
                myDeviceConnection = null;
            }
            return "closed";
        } catch (Exception e) {
            return "USB打印机关闭失败，"+e.getMessage();
        }
    }

    /*
     * 发送指令
     * */
    public void usbPrinterCommand(int f) {
        if (f < 5) {
            // 打印测试页
            if (f==2) {
                String command = pcmd.CMD_PageGO(1) + pcmd.CMD_Enter();
//                netPrinter.PrintText("打印测试\n\n",1,3,0);
//                netPrinter.PrintText(String.valueOf(printerMsg.getText()),0,2,0);
//                String a = MyUtil.formatDateTime2Num(new Date(),1);
//                netPrinter.PrintTiaoMa(a,80,50,2, 1, 2);
//                netPrinter.PageGo(1);
            }
            // 切纸
            if (f==3) {
                String command = pcmd.CMD_PageGO(1) + pcmd.CMD_Enter();
                sendMessageToPoint(command.getBytes(Charset.forName("ASCII")));
                command = pcmd.CMD_CutPage() + pcmd.CMD_Enter();
                sendMessageToPoint(command.getBytes(Charset.forName("ASCII")));
            }
            // 开钱箱
            if (f==4) {
                String command = pcmd.CMC_CashBox();
                sendMessageToPoint(command.getBytes(Charset.forName("ASCII")));
            }
        } else if (f == 5) {

        }

    }

    /**
     * 发送数据
     * @param buffer
     */
    public void sendMessageToPoint(byte[] buffer) {
        try {
            int i = myDeviceConnection.bulkTransfer(epBulkOut, buffer, buffer.length, 0);
            //System.out.println("printerInfoStr-sendMessageToPoint->:::"+i);
            if( i>= 0){
                //0 或者正数表示成功
            } else {
                Toast.makeText(usbCtx, "USB指令发送失败！", Toast.LENGTH_SHORT).show();
            }
        } catch (Exception e) {
            Toast.makeText(usbCtx, "USB指令发送失败,"+e.getMessage(), Toast.LENGTH_SHORT).show();
        }
    }

    /// <summary>
    /// 网络打印机 打印的文本
    /// </summary>
    /// <param name="pszString"></param>
    /// <param name="nFontAlign">0:居左 1:居中 2:居右</param>
    /// <param name="nfontsize">字体大小0:正常大小 1:两倍高 2:两倍宽 3:两倍大小 4:三倍高 5:三倍宽 6:三倍大小 7:四倍高 8:四倍宽 9:四倍大小 10:五倍高 11:五倍宽 12:五倍大小</param>
    /// <param name="ifzhenda">0:非针打  1:针打</param>
    public void PrintText(String pszString, int nFontAlign, int nFontSize,int ifzhenda) {
        command = pcmd.CMD_TextAlign(nFontAlign);
        outbytes =  command.getBytes(Charset.forName("ASCII"));
        sendMessageToPoint(outbytes);

        if (ifzhenda == 1)
        {
            command = pcmd.CMD_FontSize_BTP_M280(nFontSize);
            outbytes =  command.getBytes(Charset.forName("ASCII"));
            sendMessageToPoint(outbytes);

            command = pcmd.CMD_FontSize_BTP_M2801(nFontSize);
            outbytes =  command.getBytes(Charset.forName("ASCII"));
            sendMessageToPoint(outbytes);
        }
        else
        {
            command = pcmd.CMD_FontSize(nFontSize);
            outbytes =  command.getBytes(Charset.forName("ASCII"));
            sendMessageToPoint(outbytes);
        }

        command = pszString;// +CMD_Enter();
        outbytes =  command.getBytes(Charset.forName("GB2312")); //Charset.defaultCharset()); //forName("UTF-8")
        sendMessageToPoint(outbytes);
    }

    /// <summary>
    /// 网络打印机 回车
    /// </summary>
    public void PrintEnter() {
        command = pcmd.CMD_Enter();
        outbytes =  command.getBytes(Charset.forName("ASCII"));
        sendMessageToPoint(outbytes);
    }


    /// <summary>
    /// 网络打印机 切割
    /// </summary>
    /// <param name="pagenum">切割时，走纸行数</param>
    public void CutPage(int pagenum) {
        command = pcmd.CMD_PageGO(pagenum) + pcmd.CMD_Enter();
        outbytes =  command.getBytes(Charset.forName("ASCII"));
        sendMessageToPoint(outbytes);

        command = pcmd.CMD_CutPage() + pcmd.CMD_Enter();
        outbytes =  command.getBytes(Charset.forName("ASCII"));
        sendMessageToPoint(outbytes);
    }

    public void PageGo(int pagenum) {
        command = pcmd.CMD_PageGO(pagenum) + pcmd.CMD_Enter();
        outbytes =  command.getBytes(Charset.forName("ASCII"));
        sendMessageToPoint(outbytes);
    }

    /// <summary>
    /// 网络打印机换行
    /// </summary>
    /// <param name="lines"></param>
    public void PrintNewLines(int lines) {
        command = pcmd.CMD_FontSize(0);
        outbytes =  command.getBytes(Charset.forName("ASCII"));
        sendMessageToPoint(outbytes);
        for (int i = 0; i < lines; i++)
        {
            command = "" + pcmd.CMD_Enter();
            outbytes =  command.getBytes(Charset.forName("ASCII"));
            sendMessageToPoint(outbytes);
        }
    }

    /// <summary>
    /// 打开钱箱
    /// </summary>
    public void OpenCashBox() {
        command = "" + pcmd.CMC_CashBox();
        outbytes =  command.getBytes(Charset.forName("ASCII"));
        sendMessageToPoint(outbytes);
    }


    /// <summary>
    /// 打印条码
    /// </summary>
    /// <param name="numstr"></param>
    /// <param name="height"></param>
    /// <param name="width"></param>
    /// <param name="numweizi">1:上方  2:下方  0:不打印数字</param>
    /// <param name="fontalign">0:居左 1:居中 2:居右</param>
    /// <param name="fontsize">字体大小0:正常大小 1:两倍高 2:两倍宽 3:两倍大小 4:三倍高 5:三倍宽 6:三倍大小 7:四倍高 8:四倍宽 9:四倍大小 10:五倍高 11:五倍宽 12:五倍大小</param>
    public void PrintTiaoMa(String numstr, int height, int width, int numweizi, int fontalign, int fontsize) {
        command = pcmd.CMD_TiaoMaHeight(height);
        outbytes =  command.getBytes(Charset.forName("ASCII"));
        sendMessageToPoint(outbytes);

        command = pcmd.CMD_TiaoMaWidth(width);
        outbytes =  command.getBytes(Charset.forName("ASCII"));
        sendMessageToPoint(outbytes);

        command = pcmd.CMD_TiaoMaWeiZi(numweizi);
        outbytes =  command.getBytes(Charset.forName("ASCII"));
        sendMessageToPoint(outbytes);

        command = pcmd.CMD_TextAlign(fontalign);
        outbytes =  command.getBytes(Charset.forName("ASCII"));
        sendMessageToPoint(outbytes);

        command = pcmd.CMD_FontSize(fontsize);
        outbytes =  command.getBytes(Charset.forName("ASCII"));
        sendMessageToPoint(outbytes);

        command = pcmd.CMD_TiaoMaPrint(numstr);
        outbytes =  command.getBytes(Charset.forName("ASCII"));
        sendMessageToPoint(outbytes);
    }


    /*
    * caysn打印机指令
    * */

}
